var ClassicModeLayer = cc.Layer.extend({                                 
	space: null,  
	bar: null,    
	barBody: null,                                                   
	ctor: function () { 

		cc.log("ctor"); 
		this._super();  

		if(music){
			cc.audioEngine.playEffect(res.startGameEffect, false);

			cc.audioEngine.playMusic(res.playingBgMusic, true);
		}

		resetData();
		if('touches' in cc.sys.capabilities) {   //监听返回键，菜单键
			cc.eventManager.addListener({ 
				event: cc.EventListener.KEYBOARD, 
				onKeyReleased: function(keyCode, event) { 
					if (keyCode == cc.KEY.back) {   
						if(!paused){
							paused = true;
							var target = event.getCurrentTarget();
							target.addChild(new PauseLayer(target), 3);
						}
					} 
				}}, this);
		}

		curGameMode = CLASSIC_MODE;
		this.initPhysicsWorld();  

		//invoke the update()
		this.scheduleUpdate();  
		//add the ball randomly
		this.schedule(function() {	
			if(!paused){
				var randomWid = parseInt(Math.random() *(DESIGN_SIZE.width-110)+70);
				this.addBall({x:randomWid, y:DESIGN_SIZE.height-40});   
			}
		},2);

		//handle the json's widget from studio
		var gameLayer;
//		if(REAL_WIN_SIZE.height/REAL_WIN_SIZE.width == 3/2)
//		gameLayer = ccs.load(res.GAME_640X960_JSON).node;
//		else if(REAL_WIN_SIZE.height/REAL_WIN_SIZE.width == 16/9)
//		gameLayer = ccs.load(res.Game_json).node;
//		else
//		cc.log("classic1")
		gameLayer = ccs.load(res.Game_json).node;
		cc.log("classic2")
		this.addChild(gameLayer);

		scoreText = gameLayer.getChildByName("time");

		bestText = gameLayer.getChildByName("best");

		model = gameLayer.getChildByName("model");
		model.setString("经典模式");

		coinText = gameLayer.getChildByName("coin_add");
		coinText.setVisible(false);

		coins = gameLayer.getChildByName("coin");

		oldcoin = Storage.getCoin();
		if(oldcoin!=''){
			coins.setString(oldcoin);
			newcoin = parseInt(oldcoin);
		}
		else{
			coins.setString("0");
			newcoin = 0;
		}

		tips = gameLayer.getChildByName("tips");
		this.settip();

		actions = ccs.load(res.Game_json).action;
		actions.gotoFrameAndPlay(0, 400, true);
		gameLayer.runAction(actions);
		
		this.bar = this.addBar();
//		barBody;
		barShape;

//		//run the action
//		shark = ccs.load(res.Game_json).action;
//		gameLayer.runAction(shark);
//		shark.gotoFrameAndPlay(0,400,true);	
	},    
	settip : function(){

		var t = parseInt(Math.random()*35);
		tips.setString(tipArray[t]);
	},
	//initial the space
	initPhysicsWorld: function () {  
		this.space = new cp.Space();                                     
		this.setupDebugNode();                                             

		//set the gravity, the first parameter is the gravity along x axis, 
		// the second is along y axis.
		this.space.gravity = cp.v(0, 0);

		//set space's edge.
		var staticBody = this.space.staticBody;                                

		var walls = [ 
		             new cp.SegmentShape(staticBody, cp.v(0, DESIGN_SIZE.height/6),   
		            		 cp.v(DESIGN_SIZE.width, DESIGN_SIZE.height/6), 0),                       
		            		 new cp.SegmentShape(staticBody, cp.v(0, DESIGN_SIZE.height),   
		            				 cp.v(DESIGN_SIZE.width, DESIGN_SIZE.height), 0),             
		            				 new cp.SegmentShape(staticBody, cp.v(0, DESIGN_SIZE.height/6),   
		            						 cp.v(0, DESIGN_SIZE.height), 0),                    
		            						 new cp.SegmentShape(staticBody, cp.v(DESIGN_SIZE.width, DESIGN_SIZE.height/6),   
		            								 cp.v(DESIGN_SIZE.width, DESIGN_SIZE.height), 0)         
		             ];  
		for (var i = 0; i < walls.length; i++) {  
			var shape = walls[i];  
			shape.setElasticity(1);  //1: no energy consume when collided                                         
			shape.setFriction(0);   //0: no friction

			//set collisiontype, which used in the collision listener and handler
			if(i == 0)
				shape.setCollisionType(BOTTOM_WALL_COLLISION_TYPE);
			else
				shape.setCollisionType(TOP_THREE_WALL_COLLISION_TYPE);
			this.space.addStaticShape(shape);                            
		}  
	},
	addBar : function(){
		position = {x:DESIGN_SIZE.width / 2, y: DESIGN_SIZE.height / 4};
		this.barBody =  new cp.Body(10000, Infinity);//cp.momentForBox(1, barWidth, BAR_HEIGHT));  
		this.barBody.setPos(position);
		this.barBody.v = new cp.Vect(0, 0);                                   
		this.space.addBody(this.barBody);                                    

		//add the shape   
		barShape = new cp.BoxShape(this.barBody,  barWidth, BAR_HEIGHT); 
		barShape.setElasticity(1);  
		barShape.setFriction(0);  
		barShape.setCollisionType(BAR_COLLISION_TYPE);
		this.space.addShape(barShape);     

		//add the sprite 
		var sprite = new cc.PhysicsSprite(res.barPng);             
		sprite.setBody(this.barBody);                               
		sprite.setPosition(cc.p(position.x, position.y));  

		barLevel = EnhenceSys.barWidthEnhence.get();
		switch(barLevel) {
		case 1:
			sprite.setScale(5/4, 1);
			break;
		case 2:
			sprite.setScale(4/3, 1);
			break;
		}                                           
		this.addChild(sprite, 1);    

		barShape.data = sprite;   

		return sprite;
	},
	addBall: function (position) {  
		//add the body
		//shape is circle:
		//cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset)
		//m: mass; r1: inner diametor; r2: externel diametor

		//shape is rectangle:
		//cpFloat cpMomentForBox(cpFloat m, cpFloat width, cpFloat height)
		var body = new cp.Body(1, cp.momentForCircle(1, 0, BALL_RADIUS, cp.v(0, 0)));  
		body.setPos(position);  //set body's position   
		//set body's velocity, (v along x axis, y)
		body.v = new cp.Vect(ballVelocityX, ballVelocityY);                                       
		this.space.addBody(body);                                    

		//add the shape   
		var shape = new cp.CircleShape(body,  BALL_RADIUS, cp.v(0, 0)); 
		shape.setElasticity(1);  
		shape.setFriction(0);  
		shape.setCollisionType(BALL_COLLISION_TYPE);
		this.space.addShape(shape);     

		//add the sprite 
		var sprite;
		if(parseInt(tm) % coinInternal == 0){
			sprite = new cc.PhysicsSprite(res.coinPng); 
			sprite.setName(COIN_SPRITE_NAME);
		}else{
			sprite = new cc.PhysicsSprite(res.fallingBallPng); 
		}                   
		sprite.setBody(body);                               
		sprite.setPosition(cc.p(position.x, position.y));                                          
		this.addChild(sprite, 1, ballCount);    

		ballCollidedCount[ballCount] = 0;
		ballCount++;
		shape.data = sprite;   

		this.updateLevel();                                      
	},
	updateLevel: function() {

		maxCollidedCount = disappearCount + 2 * Math.round((ballCount - removedBallCount) / 5)
		+ Math.round( tm / 5);

		ballVelocityX = 300 + Math.round(((ballCount - removedBallCount) / 5)) * 10;
		ballVelocityY = 300 + Math.round(((ballCount - removedBallCount) / 5)) * 10;
	},
	update: function (dt) {  
		//invoke the method that update the interface in the engine
		//the timeStep is the interval.
		if(!paused){
			var timeStep = 0.03;                                                
			this.space.step(timeStep);   

			 //tm is program's running time
			tm +=dt;      
			scoreText.setString(tm.toFixed(2)+"\"");
		}                             
	},
	onEnter : function () {

		cc.log("enter");
		tm = 0;
		this._super();

//		cc.log(1)
//		cc.sys.dumpRoot();
//		cc.log(2)
//		cc.sys.garbageCollect();
//		cc.log(3)
		//add the collision listener
		//listen the collision between ballA and ballB
		this.space.addCollisionHandler(BALL_COLLISION_TYPE, BALL_COLLISION_TYPE,
				this.collisionBegin.bind(this),
				this.collisionPre.bind(this),
				this.collisionPost.bind(this),
				this.collisionSeparate.bind(this)
		); 
		//listen the collision between ball and space's top, left, right edge 
		this.space.addCollisionHandler(BALL_COLLISION_TYPE, TOP_THREE_WALL_COLLISION_TYPE,
				this.collisionBegin.bind(this),
				this.collisionPre.bind(this),
				this.collisionPost.bind(this),
				this.collisionSeparate.bind(this)
		);
		//listen the collision between ball and space's bottom edge
		this.space.addCollisionHandler(BALL_COLLISION_TYPE, BOTTOM_WALL_COLLISION_TYPE,
				this.collisionBegin.bind(this),
				this.collisionPre.bind(this),
				this.collisionPost.bind(this),
				this.collisionSeparate.bind(this)
		);
		//listen the collision between ball and bar
		this.space.addCollisionHandler(BALL_COLLISION_TYPE, BAR_COLLISION_TYPE,
				this.collisionBegin.bind(this),
				this.collisionPre.bind(this),
				this.collisionPost.bind(this),
				this.collisionSeparate.bind(this)
		);

		this.highscore();
		var listener = cc.EventListener.create({
			event: cc.EventListener.TOUCH_ONE_BY_ONE,
			swallowTouches: true, 
			onTouchBegan: function (touch, event) {

				var target = event.getCurrentTarget();
				//cc.Director.getInstance().runScene(new ClassicModeScene());
				moveDelta = {
						x: 0,
						y: 0
				};
				return true;
			},
			onTouchMoved: function (touch, event) {
				var target = event.getCurrentTarget();
				var delta = touch.getDelta();
				moveDelta = delta;

				if(delta.x > 0){
					if(DESIGN_SIZE.width - (target.bar.x + target.bar.width/2) < delta.x)
						delta.x = DESIGN_SIZE.width - (target.bar.x + target.bar.width/2);
				}else{
					if((target.bar.x - target.bar.width/2) < -delta.x)
						delta.x = -(target.bar.x - target.bar.width/2);
				}
				if(delta.y > 0){
					if(DESIGN_SIZE.height * 2 / 3 - (target.bar.y + target.bar.height/2) 
							< delta.y)
						delta.y = DESIGN_SIZE.height * 2 / 3 - 
						(target.bar.y + target.bar.height/2);
				}else{
					if((target.bar.y - target.bar.height/2 - DESIGN_SIZE.height / 6) 
							< -delta.y)
						delta.y = -(target.bar.y - target.bar.height/2 - DESIGN_SIZE.height / 6);
				}
				position = {
						x:target.bar.x + delta.x,
						y:target.bar.y + delta.y
				};
				if(!paused){
					
//					var action = cc.moveBy(1, delta);
//					target.bar.runAction(action);
					target.bar.setPosition(position);

					target.barBody.v = new cp.Vect(0, 0);
				}
			},

			onTouchEnded: function (touch, event) { 
				if(moveDelta.x == 0 && moveDelta.y == 0){
					if(!paused)
						if(oldtime == -1)
							oldtime = tm;
						else{
							if(tm - oldtime < 0.5){
								paused = true;
								var target = event.getCurrentTarget();
//								target.space.removeCollisionHandler(BALL_COLLISION_TYPE, BALL_COLLISION_TYPE);
//								target.space.removeCollisionHandler(BALL_COLLISION_TYPE, BOTTOM_WALL_COLLISION_TYPE);
//								target.space.removeCollisionHandler(BALL_COLLISION_TYPE, TOP_THREE_WALL_COLLISION_TYPE);
//								target.space.removeCollisionHandler(BALL_COLLISION_TYPE, BAR_COLLISION_TYPE);
								event.getCurrentTarget().getParent()
								.addChild(new PauseLayer(target), 3);
							}
							oldtime = -1;
						}

				}else
					oldtime = -1;
			},
			onTouchCancelled : function(touch, event){
			}

		});

		cc.eventManager.addListener(listener, this);
		return true;
	},
	//the method will be invoked when the collision happens.
	collisionBegin : function ( arbiter, space ) {
		cc.log("begin")
		var shapes = arbiter.getShapes();
		 
		var shapeA = shapes[0];
		var shapeB = shapes[1];

		var collTypeA = shapeA.collision_type;
		var collTypeB = shapeB.collision_type;

		if(shapeA.data.getName() != COIN_SPRITE_NAME){
			shapeA.data.setTexture(res.collidedBallPng);

			this.scheduleOnce(function(){
				if(shapeA.getBody().v.y < 0)
					shapeA.data.setTexture(res.fallingBallPng);
				else
					shapeA.data.setTexture(res.flyingBallPng);
			}, 0.5);
		}

		switch(collTypeB){
		case BALL_COLLISION_TYPE:

			var ballA = shapeA.data;
			var ballB = shapeB.data;

			if(music)
				cc.audioEngine.playEffect(res.ballCollidedEffect, false);

			if(ballB.getName() != COIN_SPRITE_NAME){
				ballB.setTexture(res.collidedBallPng);

				this.scheduleOnce(function(){
					if(shapeB.getBody().v.y < 0)
						ballB.setTexture(res.fallingBallPng);
					else
						ballB.setTexture(res.flyingBallPng);
				}, 0.5);
			}

			this.space.addPostStepCallback(function () {
				if(ballCollidedCount[ballA.getTag()] >= maxCollidedCount ||
						ballCollidedCount[ballA.getTag()] == -1){
					if(music)
						cc.audioEngine.playEffect(res.ballDisappearEffect, false);

					position = {x:ballA.x, y:ballA.y};
					this.showBoom(position);

					position = {x:ballA.x, y:ballA.y};
					this.showBoom(position);

					removedBallCount++;

					ballCollidedCount[ballA.getTag()] = -1;
					this.space.removeShape(shapeA);
					//shapeA.free();
					this.space.removeBody(shapeA.getBody());
					//shapeA.getBody.free();
					ballA.removeFromParent(true);

				}else
					ballCollidedCount[ballA.getTag()]++;

				if(ballCollidedCount[ballB.getTag()] >= maxCollidedCount ||
						ballCollidedCount[ballB.getTag()] == -1){
					if(music)
						cc.audioEngine.playEffect(res.ballDisappearEffect, false);

					position = {x:ballB.x, y:ballB.y};
					this.showBoom(position);

					position = {x:ballB.x, y:ballB.y};
					this.showBoom(position);

					removedBallCount++;
					ballCollidedCount[ballB.getTag()] = -1;
					this.space.removeShape(shapeB);
					//shapeA.free();
					this.space.removeBody(shapeB.getBody());
					//shapeA.getBody.free();
					ballB.removeFromParent(true);
				}else
					ballCollidedCount[ballB.getTag()]++;
			}.bind(this));
			break;
		case TOP_THREE_WALL_COLLISION_TYPE:
//			var ballA = shapeA.data;

			this.space.addPostStepCallback(function () {
//				if(ballCollidedCount[ballA.getTag()] == maxCollidedCount ||
//				ballCollidedCount[ballA.getTag()] == -1){
//				removedBallCount++;
//				ballCollidedCount[ballA.getTag()] = -1;
//				this.space.removeShape(shapeA);
//				//shapeA.free();
//				this.space.removeBody(shapeA.getBody());
//				//shapeA.getBody.free();
//				ballA.removeFromParent(true);
//				}else
//				ballCollidedCount[ballA.getTag()]++;
				//cc.log("Top Left Right edge");
			}.bind(this));
			break;
		case BAR_COLLISION_TYPE:
			var ballA = shapeA.data;

			this.space.addPostStepCallback(function () {
				if(ballA.getName() == COIN_SPRITE_NAME){
					if(music)
						cc.audioEngine.playEffect(res.collectedCoinEffect, false);

					var coinAdd = Math.round(Math.random() * 100) + 20;
					coinText.setString(coinAdd + "");
					coinText.setVisible(true);
					this.scheduleOnce(function(){
						coinText.setVisible(false);

					}, 1);

					newcoin += coinAdd;
					coins.setString(newcoin+"");

					removedBallCount++;
					ballCollidedCount[ballA.getTag()] = -1;
					this.space.removeShape(shapeA);
					//shapeA.free();
					this.space.removeBody(shapeA.getBody());
					//shapeA.getBody.free();
					ballA.removeFromParent(true);
				} else{
					if(music)
						cc.audioEngine.playEffect(res.barCollidedEffect, false);
				}
			}.bind(this));
			break;
		case BOTTOM_WALL_COLLISION_TYPE:
			var ballA = shapeA.data;

			this.space.addPostStepCallback(function () {
				if(ballA.getName() == COIN_SPRITE_NAME){

					position = {x:ballA.x, y:ballA.y};
					this.showBoom(position);

					removedBallCount++;
					ballCollidedCount[ballA.getTag()] = -1;
					this.space.removeShape(shapeA);
					//shapeA.free();
					this.space.removeBody(shapeA.getBody());
					//shapeA.getBody.free();
					ballA.removeFromParent(true);
				}else{
					if(music)
						cc.audioEngine.playEffect(res.deadEffect, false);

//					var scene = new cc.Scene();
//					var layer = new EndLayer(tm.toFixed(2));
//					scene.addChild(layer);
//					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, BALL_COLLISION_TYPE)
//					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, BAR_COLLISION_TYPE)
//					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, TOP_THREE_WALL_COLLISION_TYPE)
//					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, BOTTOM_WALL_COLLISION_TYPE)
					sys.localStorage.setItem(COIN_COUNT_TAG ,newcoin);
//					cc.eventManager.removeAllListeners();
					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, BALL_COLLISION_TYPE);
					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, BOTTOM_WALL_COLLISION_TYPE);
					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, TOP_THREE_WALL_COLLISION_TYPE);
					this.space.removeCollisionHandler(BALL_COLLISION_TYPE, BAR_COLLISION_TYPE);

					cc.Director.getInstance().replaceScene(new EndScene(tm.toFixed(2)));

				}
			}.bind(this));
			break;
		}

		return true;
	},
	collisionPre : function ( arbiter, space ) {
		cc.log('collision pre');
		return true;
	},
	collisionPost : function ( arbiter, space ) {
		cc.log('collision post');
	},
	collisionSeparate : function ( arbiter, space ) {
		cc.log('collision separate');
	},

	setupDebugNode: function () {
		this._debugNode = new cc.PhysicsDebugNode(this.space);                   
		this._debugNode.visible = DEBUG_NODE_SHOW;                            
		this.addChild(this._debugNode);                                     
	},
	highscore: function(){
		var sc = sys.localStorage.getItem(CLASSIC_BEST_SCORE_TAG);
		var now = parseFloat(tm);
		if(!(sc=="")){

			var old = parseFloat(sc);
			if(now>old){
				sys.localStorage.setItem(CLASSIC_BEST_SCORE_TAG ,tm);
				bestText.setString("Best:"+now.toFixed(2)+"\"");
			}else{
				bestText.setString("Best:"+old.toFixed(2)+"\"");
			}
		}else{
			sys.localStorage.setItem(CLASSIC_BEST_SCORE_TAG ,tm);
			bestText.setString("Best:"+now.toFixed(2)+"\"");
		}
	},
	showBoom : function(positon){
		if(music)
			cc.audioEngine.playEffect(res.boomEffect, false);

		var boomSprite = cc.Sprite(res.boomPng);

		boomSprite.attr(position);
		boomSprite.setScale(0.1, 0.1);
		this.addChild(boomSprite, 1);

		//boom's action
		boomSprite.opacity = 0;
		fadeOut = cc.fadeTo(0.3, 255);
		scale = cc.scaleTo(0.3, 0.8, 0.8);
		spawn = cc.spawn(fadeOut, scale);
		fade = cc.fadeTo(0.2, 0);
		sequence = cc.sequence(spawn, fade);

		boomSprite.runAction(sequence);
	}
});

var ClassicModeSceneWithStudio = cc.Scene.extend({
	onEnter:function () {
		this._super();
		var layer = new ClassicModeLayer();
		this.addChild(layer);
	}
});

